<template>
  <div class="app-container">
    <el-row>
      <div class="chart-title">css图形</div>
    </el-row>
    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="24" class="cssicon clearfix">
        <div class="icon icon_triangle"/>
        <div class="icon icon_triangle1"/>
        <div class="icon icon_triangle2"/>
        <div class="icon icon_triangle3"/>

        <div class="icon wrapper">
          <div class="triangle"><div/></div>
          欢迎来到cssChart
        </div>

        <div class="icon icon_num">6</div>
      </el-col>

    </el-row>

    <el-row>
      <div class="chart-title">canvas图标</div>
    </el-row>
    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="24" class="cssicon clearfix">
        <div class="icon canvans1">
          <canvas id="cv1" width="400" height="400"/>
        </div>
        <div class="icon canvans1">
          <canvas id="cv2" width="400" height="400"/>
        </div>
        <div class="icon canvans1">
          <canvas id="cv3" width="400" height="400"/>
        </div>

        <div class="icon canvans1">
          <canvas id="cv4" width="400" height="400" style="border: 1px solid red"/>
        </div>

        <div class="icon canvans1">
          <canvas id="cv5" width="400" height="400" style="border: 1px solid #94e5ff"/>
        </div>

        <div class="icon canvans1">
          <canvas id="cv6" width="400" height="400" style="border: 1px solid #94e5ff"/>
        </div>

        <!--<div class="icon canvans1">
          <canvas id="cv7" width="400" height="400" style="border: 1px solid #94e5ff"/>
        </div>-->

        <div class="icon canvans1">
          <canvas id="cv8" width="400" height="400" style="border: 1px solid #94e5ff"/>
        </div>

      </el-col>

    </el-row>
  </div>
</template>

<script>

export default {

  data() {
    return {

    }
  },
  mounted() {
    this.pix()
    this.canvansInit()
  },
  methods: {
    // 像素操作
    pix() {
      const cv8 = document.getElementById('cv8')
      const ctx = cv8.getContext('2d')
    },
    canvansInit() {
      // 画线
      /* const cv1 = document.getElementById('cv1')
      const ctx1 = cv1.getContext('2d')
      this.getLine(ctx1, 0, 0, 400, 500)*/

      // 画矩形
      /* const cv2 = document.getElementById('cv2')
      const ctx2 = cv2.getContext('2d')
      this.getRectangle(ctx2, 10, 10, 50, 50)*/

      const cv1 = document.getElementById('cv1')
      const ctx1 = cv1.getContext('2d')
      // 画y轴坐标
      this.getLine(ctx1, 0, 0, 0, 400)

      // 画x轴坐标
      this.getLine(ctx1, 0, 400, 400, 400)

      for (let i = 0; i < 4; i++) {
        this.getLine(ctx1, 0, i * 100, 10, i * 100)
      }

      for (let i = 0; i < 5; i++) {
        // 随机高度
        const h = Math.random() * 300 + 10
        // 随机颜色
        // const color = `#` + parseInt(Math.random() * 0xffffff).toString(16)
        const color = 'rgb(' + parseInt(Math.random() * 256) + ',' + parseInt(Math.random() * 256) + ',' +
        parseInt(Math.random() * 256) + ')'
        console.log(color)
        this.getRectangleFill(ctx1, 50 + 70 * i, 400 - h, 20, h, color)
      }

      /**
       * 画水杯
       */

      const cv2 = document.getElementById('cv2')
      const ctx2 = cv2.getContext('2d')

      // 起始点
      const x = 150
      const y = 150
      // 杯子宽高
      const size = 100
      const r = 10

      // 杯体
      this.getRectangleStroke(ctx2, x, y, size, size)
      // 把手
      this.getCircular(ctx2, x + 100, y + size / 2, size / 4, -Math.PI / 2, Math.PI / 2)
      for (let i = 0; i < 5; i++) {
        // 热气
        this.getCircular(ctx2, x + 10 + i * 20, y - 50, r, Math.PI / 2, 3 / 2 * Math.PI)
        this.getCircular(ctx2, x + 10 + i * 20, y - 50 + 2 * r, r, -Math.PI / 2, Math.PI / 2)
      }

      /**
       * 画动态的圆
       */

      const cv3 = document.getElementById('cv3')
      const ctx3 = cv3.getContext('2d')
      const c = (Math.PI * 2) / 360
      // 方法1
      /* let start = -Math.PI / 2
      let end = -Math.PI / 2 + c
      const temr = setInterval(() => {
        if (end >= (3 / 2 * Math.PI)) {
          clearInterval(temr)
        }
        this.getCircular(ctx3, 200, 200, 100, start, end)

        start = end
        end = end + c
      }, 10)*/

      // 方法2
      let count = 0
      const temr2 = setInterval(() => {
        count++
        this.getCircular(ctx3, 200, 200, 100, -Math.PI / 2, count * c - Math.PI / 2)
        if (count === 360) {
          clearInterval(temr2)
        }
      }, 10)

      // 碰撞检测
      this.collisionFun()
      const cv5 = document.getElementById('cv5')
      // cv5.width = document.documentElement.clientWidth
      // cv5.height = document.documentElement.clientHeight
      const ctx5 = cv5.getContext('2d')
      // 画文字 可另存为图片
      this.getText(ctx5, 'hello', 200, 200)

      // 方法1
      /* for (let i = 0; i < 400; i += 10) {
        this.getLine(ctx5, i, i, i + 5, i + 5)
        this.getLine(ctx5, 400 - i, i, 400 - (i + 5), i + 5)
      }*/
      // 方法2
      ctx5.setLineDash([5, 5])// 线的长度 空白长度
      this.getLine(ctx5, 0, 0, 400, 400)
      this.getLine(ctx5, 400, 0, 0, 400)

      // 画线性小球
      this.getCircularLine()

      // 鼠标跟随小球
      // this.getCircularMouse()
    },
    // 鼠标坐标获取不对
    getCircularMouse() {
      const cv7 = document.getElementById('cv7')
      const ctx = cv7.getContext('2d')
      const w = 400
      const h = 400
      const _this = this
      function Ball(x, y) {
        const ball_this = this
        // 坐标
        this.x = x
        this.y = y
        // 半径
        this.r = 60

        this.color = `#` + parseInt(Math.random() * 0xffffff).toString(16)

        this.show = function() {
          // 半径逐渐变小
          ball_this.r--
          _this.getCircularFill(ctx, ball_this.x, ball_this.y, ball_this.r, ball_this.color)
        }
      }

      const ballArr = []
      window.onmousemove = function(e) {
        // console.log(e.x, e.y)
        var ball = new Ball(e.x, e.y)
        ballArr.push(ball)
        ball.show()
      }

      setInterval(() => {
        ctx.clearRect(0, 0, w, h)
        for (let i = 0; i < ballArr.length; i++) {
          const ball = ballArr[i]
          if (ball.r <= 0) {
            ballArr.splice(i, 1)
          } else {
            ball.show()
          }
        }
      }, 30)
    },
    getCircularLine() {
      const cv6 = document.getElementById('cv6')
      const ctx = cv6.getContext('2d')

      // 画布属性
      const w = 400
      const h = 400
      const _this = this
      function Ball(text) {
        const ball_this = this
        // 坐标
        this.x = 60 // _this.getRandom(5) + 60
        this.y = 60 // _this.getRandom(3) + 60 // 确保球能在坐标系内
        // 半径
        this.r = _this.getRandom(50) + 10 // [10~60)
        this.text = text

        this.color = `#` + parseInt(Math.random() * 0xffffff).toString(16)

        // x y速度
        this.xSp = _this.getRandom(3) + 2
        this.ySp = _this.getRandom(3) + 1

        this.run = function() {
          if (ball_this.x + ball_this.r > w || ball_this.x - ball_this.r <= 0) {
            ball_this.xSp = -ball_this.xSp
          }
          ball_this.x += ball_this.xSp
          if (ball_this.y + ball_this.r > h || ball_this.y - ball_this.r <= 0) {
            ball_this.ySp = -ball_this.ySp
          }
          ball_this.y += ball_this.ySp
        }

        this.show = function() {
          ball_this.run()
          _this.getCircularFill(ctx, ball_this.x, ball_this.y, ball_this.r, ball_this.color)
          _this.getText(ctx, ball_this.text, ball_this.x + ball_this.r, ball_this.y)
        }
      }

      const ballArr = []
      const textArr = ['CSS', 'HTML', 'JAVASCRIPT', 'VUE', 'TYPESCRIPT']
      // 创建球
      for (let i = 0; i < 5; i++) {
        const ball = new Ball(textArr[i])
        ballArr.push(ball)
        ball.show()
        // console.log(ball)

        // 连线
        for (let j = 0; j < i; j++) {
          _this.getLine(ctx, ball.x, ball.y, ballArr[j].x, ballArr[j].y)
        }
      }

      // 运动
      setInterval(() => {
        ctx.clearRect(0, 0, w, h)
        for (let i = 0; i < ballArr.length; i++) {
          const ball = ballArr[i]
          ball.show()
          // 连线
          for (let j = 0; j < i; j++) {
            _this.getLine(ctx, ball.x, ball.y, ballArr[j].x, ballArr[j].y)
          }
        }
      }, 30)
    },
    /**
     *
     * @param src 图片地址3，5，9个参数有的值
     * @param sx 剪切的坐标
     * @param sy 剪切的坐标
     * @param sw 剪切的宽
     * @param sh 剪切的高度
     * @param x 放在画布的坐标  3，5个参数有的值
     * @param y 放在画布的坐标  3，5个参数有的值
     * @param w 画布上显示的宽度 5个参数有的值
     * @param h 画布上显示的高度 5个参数有的值
     *
     */
    drawImage(src, sx, sy, sw, sh, x, y, w, h) {

    },
    /**
     *
     * @param ctx
     * @param text 文本
     * @param x 坐标
     * @param y 坐标
     * @param maxWidth 允许的最大文本宽度 文字放不下时会挤压文字
     */
    getText(ctx, text, x, y, maxWidth) {
      ctx.beginPath()
      // 设置字体
      ctx.font = '18px 微软雅黑'
      ctx.fillStyle = 'red'
      ctx.strokeStyle = 'green'
      ctx.textAlign = 'top'
      // 水平居中
      // ctx.textAlign = 'center'
      // 垂直居中
      // ctx.textBaseline = 'middle'
      if (maxWidth) {
        ctx.fillText(text, x, y, maxWidth)
        return
      }

      // fillText实心文字
      ctx.fillText(text, x, y)
      // strokeText空心文字
      // ctx.strokeText(text, x, y)
    },
    collisionFun() {
      const cv4 = document.getElementById('cv4')
      const ctx4 = cv4.getContext('2d')

      // 画布属性
      const w = 400
      const h = 400
      /* // 起点坐标
      let x = 100
      let y = 50
      const r = 20
      let xSp = 5
      let ySp = 5

      // this.getRectangleStroke(ctx4, 0, 0, w, h)

      setInterval(() => {
        if (x + r > w || x - r <= 0) {
          xSp = -xSp
        }
        if (y + r > h || y - r <= 0) {
          ySp = -ySp
        }
        ctx4.clearRect(0, 0, w, h)
        x += xSp
        y += ySp
        this.getCircularFill(ctx4, x, y, r)
      }, 50)*/
      const _this = this
      function Ball() {
        const ball_this = this
        // 坐标
        this.x = 60 // _this.getRandom(5) + 60
        this.y = 60 // _this.getRandom(3) + 60 // 确保球能在坐标系内
        // 半径
        this.r = _this.getRandom(50) + 10 // [10~60)

        this.color = `#` + parseInt(Math.random() * 0xffffff).toString(16)

        // x y速度
        this.xSp = _this.getRandom(3) + 2
        this.ySp = _this.getRandom(3) + 1

        this.run = function() {
          if (ball_this.x + ball_this.r > w || ball_this.x - ball_this.r <= 0) {
            ball_this.xSp = -ball_this.xSp
          }
          ball_this.x += ball_this.xSp
          if (ball_this.y + ball_this.r > h || ball_this.y - ball_this.r <= 0) {
            ball_this.ySp = -ball_this.ySp
          }
          ball_this.y += ball_this.ySp
        }

        this.show = function() {
          ball_this.run()
          // console.log("=================",ball_this.x, ball_this.y)
          _this.getCircularFill(ctx4, ball_this.x, ball_this.y, ball_this.r, ball_this.color)
        }
      }

      const ballArr = []
      // 创建球
      for (let i = 0; i < 500; i++) {
        const ball = new Ball()
        ballArr.push(ball)
        ball.show()
        // console.log(ball)
      }

      // 运动
      setInterval(() => {
        ctx4.clearRect(0, 0, w, h)
        for (let i = 0; i < ballArr.length; i++) {
          const ball = ballArr[i]
          ball.show()
        }
      }, 30)
    },
    // 返回随机数
    getRandom(num) {
      return Math.random() * num
    },
    // 清除矩形画布
    clearRect(ctx, x, y, w, h) {
      ctx.clearRect(x, y, w, h)
    },
    // 话直线
    getLine(ctx, bx, by, ex, ey, color, width) {
      ctx.beginPath()
      ctx.moveTo(bx, by)
      ctx.lineTo(ex, ey)
      ctx.strokeStyle = color || '#94e5ff'
      ctx.lineWidth = width || 1

      // 着色 不然显示不出来
      ctx.stroke()
      ctx.closePath()
    },
    // 只能填充的矩形 不能描边
    getRectangleFill(ctx, x, y, w, h, color) {
      ctx.beginPath()
      ctx.fillStyle = color || 'red'
      ctx.fillRect(x, y, w, h)
      ctx.closePath()
    },
    // 只能描边
    getRectangleStroke(ctx, x, y, w, h, color, width) {
      ctx.beginPath()
      ctx.strokeStyle = color || '#94e5ff'
      ctx.lineWidth = width || 1
      ctx.strokeRect(x, y, w, h)
    },
    // 通用的画矩形
    /**
     *
     * @param ctx 画笔
     * @param x 起始坐标
     * @param y 起始坐标
     * @param w 宽
     * @param h 高
     * @param color 矩形边框颜色
     * @param width 矩形边框宽度
     * @param fillColor 填充颜色
     */
    getRectangle(ctx, x, y, w, h, color, width, fillColor) {
      ctx.rect(x, y, w, h)

      // 如果需要描边和填充时先填充再描边 否则填充会覆盖一部分描边
      if (fillColor) {
        ctx.fillStyle = fillColor || 'red'
        ctx.fill()
      }
      ctx.strokeStyle = color || '#94e5ff'
      ctx.lineWidth = width || 5
      ctx.stroke()

      // ctx.closePath()
    },
    getCircularFill(ctx, x, y, r, fillColor) {
      ctx.beginPath()
      ctx.fillStyle = fillColor || '#94e5ff'
      ctx.arc(x, y, r, 0, Math.PI * 2)
      ctx.fill()
    },
    /** *
     *
     * @param ctx
     * @param x 起始坐标
     * @param y 起始坐标
     * @param r 半径
     * @param startAngle 起始角度
     * @param endAngle 结束角度
     * @param direction 顺时针false 逆时针 true
     */
    getCircular(ctx, x, y, r, startAngle, endAngle, direction, strokeColor, width, fillColor) {
      // 默认关闭上一次
      ctx.beginPath()
      if (fillColor) {
        ctx.fillStyle = fillColor
        ctx.fill()
      }
      ctx.strokeStyle = strokeColor || '#94e5ff'
      ctx.lineWidth = width || 1
      ctx.arc(x, y, r, startAngle, endAngle, direction)
      ctx.stroke()
    }
  }
}

</script>

<style scoped>
  .canvans1{
    margin-right: 20px;
    margin-bottom: 50px;
  }
.icon_num{
  width: 50px;
  line-height: 50px;
  background-color: #bbffff;
  text-align: center;
  color: black;
  border-radius: 80% 90% 100% 20%;
  margin-left: 20px;

}
  .wrapper{
    position: relative;
    padding: 20px 30px;
    border: 1px solid red;
    border-radius: 10px;
    text-align: center;
    background-color: #94e5ff;
    margin-left: 20px;

  }
  .triangle{
    position: absolute;
    top:-30px;
    left: 50%;
    margin-left: -15px;
    border-width: 15px;
    border-color: transparent transparent red transparent;
    border-style: solid;
  }
  .triangle div{
    position: absolute;
    top:-13px;
    left:-14px;
    border-width: 14px;
    border-style: solid;
    border-color: transparent transparent #bbffff transparent;
  }
  .cssicon div{
    float: left;

  }
  .icon_triangle{
    width: 0;
    border-width: 20px;
    border-style: solid;
    border-color: #94e5ff transparent transparent  transparent;
  }
  .icon_triangle1{
    /*width: 30px;*/
    border-width: 20px;
    border-style: solid;
    border-color: transparent transparent  #94e5ff transparent;
  }
  .icon_triangle2{
   /* width: 30px;*/
    border-width: 20px;
    border-style: solid;
    border-color: transparent #94e5ff transparent   transparent;
  }
  .icon_triangle3{
    border-width: 20px;
    border-style: solid;
    border-color: transparent  transparent   transparent #94e5ff;
    /*transform: rotate(45deg);*/
  }
  .icon+.icon{
    margin-left: 20px;
  }
  .cssicon{
    display: inline-block;
  }

  .app-container {
    background-color: #171c3c;
  }

  .chart-title {
    width: 100%;
    text-align: center;
    height: 80px;
    line-height: 80px;
    font-size: 24px;
    color: #fff;
    position: relative;
    margin-top: 20px;
    margin-bottom: 10px;
  }

</style>

